package com.only4play.session.local;

import com.only4play.auth.CodeContent;
import com.only4play.auth.ExpirationPolicy;
import com.only4play.session.CodeManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liyuncong
 * @version 1.0
 * @file LocalCodeManager
 * @brief 本地授权码管理
 * @details 本地授权码管理
 * @date 2023-11-18
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2023-11-18               liyuncong          Created
 */
@Slf4j
@Component
public class LocalCodeManager implements CodeManager, ExpirationPolicy {

    private final Map<String, DummyCode> codeMap = new ConcurrentHashMap<>();

    @Override
    public void create(String code, CodeContent codeContent) {
        long expired = Instant.now().plusSeconds(getExpiresIn()).toEpochMilli();
        codeMap.put(code, new DummyCode(codeContent, expired));
        log.info("success generate access code: {}", code);
    }

    @Override
    public CodeContent getAndRemove(String code) {
        DummyCode dummyCode = codeMap.remove(code);
        if (Objects.isNull(dummyCode) || Instant.now().isAfter(Instant.ofEpochMilli(dummyCode.expired))) {
            return null;
        }
        return dummyCode.codeContent;
    }

    @Scheduled(cron = SCHEDULED_CORN)
    @Override
    public void verifyExpired() {
        codeMap.forEach((code, dummyCode) -> {
            if (Instant.now().isAfter(Instant.ofEpochMilli(dummyCode.expired))) {
                codeMap.remove(code);
                log.info("access code expired, code: {}", code);
            }
        });
    }

    private record DummyCode(CodeContent codeContent, long expired) {
    }

}
